// ## 2023/09/01 # 黑店小小二 # 修复征兵数量过多 ##
// ## 2023/05/02 # 江东新风 # 将征兵函数迁回，改变写法以适应内政官的调用 ##
// ## 2023/04/20 # 江东新风 # 删掉计算过程中的提示，出现2次很诡异 ##
// ## 2022/11/01 # 铃 # 征兵改为招兵,AI和玩家使用不同逻辑. ##
// ## 2022/08/14 # 铃 # 在新的人口系统中,征兵的逻辑也发生了很大变化,重做相关函数。 ##
// ## 2021/10/10 # 江东新风 # 人口相关设定 ##
// ## 2021/10/01 # 江东新风 # namespace的韩文改成英文 ##
// ## 2021/09/15 # 江东新风 # 更改pk::core[]函数为英文##
// ## 2021/01/24 # 江东新风 # 将函数内容全搬运到305，以便其他cpp调用 ##
// ## 2020/10/23 #江东新风#同步马术书大神的更新，修复战役模式及势力无都督等情况的nullptr错误##
// ## 2020/08/24 # 氕氘氚 # 常量修改 ##
// ## 2020/08/16 #江东新风#has_skill函数替換##

/*
@수정자 : 기마책사
@Update: '18.10.14  // 수정내용: 세력의 보유 특기 또는 황군인 경우 징병량 버프
@Update: '19.04.26  // 수정내용: 대도시 징병량 버프 추가
@Update: '19.05.4   // 수정내용: 유저_도시수_패널티 추가
@Update: '20.8.25   // 수정내용: null point error 오류 수정
@Update: '20.8.29  // 수정내용: 캠페인에서는 커스텀 세팅 사용 불가하도록 수정
*/

namespace RECRUIT_TROOPS_CHANGE
{
	//---------------------------------------------------------------------------

	// const bool 势力名声特技修正 = true;	   // 군주,도독,태수가 명성 특기 보유 시 버프
	// const float 名声特技_君主名声 = 1.10f; // 군주 버프 계수
	// const float 名声特技_都督名声 = 1.15f; // 도독 버프 계수
	// const float 名声特技_太守名声 = 1.20f; // 태수 버프 계수
	// const bool 皇帝势力修正 = true;		   // 후한 황제 옹립 세력 또는 군주가 황제인 경우 버프

	const bool 征兵数_城市数_修正 = false; // 유저세력에 대해서 도시수에 비례하여 징병량 디버프 (도시당 1% 감소)

	//---------------------------------------------------------------------------

	class Main
	{
		Main()
		{
			pk::set_func(100, pk::func100_t(callback));
		}

		int callback(pk::building @building, const pk::detail::arrayptr<pk::person @>& in actors, int type /*0执行，1仅计算，不影响兵役*/)
		{
			pk::list<pk::person @> actor_list;
			for (int i = 0; i < actors.length; i++)
			{
				actor_list.add(actors[i]);
			}

			int n = get_recruit_num(building, actor_list, type);

			return n;
		}
		/**/
		float func_5c4600(pk::city @city)
		{
			int level1 = 0, level2 = 0;
			for (int i = 0; i < int(city.max_devs); i++)
			{
				pk::building @building = city.dev[i].building;
				if (pk::is_alive(building))
				{
					switch (building.facility)
					{
						case 시설_병영:
							building.completed ? level1++ : 0;
							break;
						case 시설_병영2단:
							building.completed ? level2++ : level1++;
							break;
						case 시설_병영3단:
							building.completed ? 0 : level2++;
							break;
					}
				}
			}
			if (int(city.barracks_counter) > level1 + level2)
				return 1.5f;
			if (int(city.barracks_counter) > level1)
				return 1.2f;
			if (level1 > 0)
				return 1.f;
			return 0.3f;
		}

		// 内政官经验无法互动,玩家不知道,在有办法之前先把影响系数降低
		float get_exp_eff(int person_id)
		{
			if (pk::is_valid_person_id(person_id))
			{
				auto person_t = ch::get_person_p(person_id);
				if (person_t.recruit_exp < 执政官经验一阶)
					return 1.0f;
				if (person_t.recruit_exp < 执政官经验二阶)
					return 1.03f;
				if (person_t.recruit_exp < 执政官经验三阶)
					return 1.05f;
				return 1.1f;
			}
			return 1.0f;
		}
	}

	Main main;

	// 自动内政时还需考虑金钱投入量对征兵数量的影响
	// int troops_base_gain = int((sqrt(building_p.troops_effic) + building_p.troops_effic * 0.03) * 最终修正);
	// 最终修正 = 难度系数 * 君主能力修正;
	// building_p.troops_gain = int(招兵效率 * troops_base_gain * 30);
	int get_recruit_num(pk::building @building, pk::list<pk::person @> actor_list, int type = 1 /*0执行，1仅计算，不影响兵役*/)
	{
		int n = 0;
		int sum = 0;
		int mul = 100;
		int building_id = building.get_id();
		if (pk::is_valid_base_id(building_id) and actor_list.count != 0 and actor_list[0] !is null)
		{
			int max = 0;
			bool has_skill = false;
#if param_set
			int skill_id = pk::get_recruit_param().skill; // int(pk::core["recruit.skill"]);
#endif
#if not_param_set
			int skill_id = int(pk::core["recruit.skill"]);
#endif
			for (int i = 0; i < actor_list.count; i++)
			{
				pk::person @actor = actor_list[i];
				if (pk::is_alive(actor))
				{
#if param_set
					int s = actor.stat[pk::get_recruit_param().stat]; // int(pk::core["recruit.stat"])];
#endif
#if not_param_set
					int s = actor.stat[int(pk::core["recruit.stat"])];
#endif
					// pk::trace("produce stat:" + s);
					// 此处应引入内政经验概念来抵消人数多的优势,倍率最高1.5倍，只对内政官模式生效
					// 同时参考装备生产，采用sum+max模式，增加能力最高武将的权重，同时也就对内政官模式做出平衡
					sum = sum + s;
					max = pk::max(max, s);
					if (ch::has_skill(actor, skill_id))
						has_skill = true;
				}
			}
			if (has_skill)
				mul += pk::core::skill_constant_value(skill_id);

			float exp_eff = 1.0f;
			float absent_eff = 1.0f;
			float expend_eff = 1.0f;
			// 统计下来,自动内政的征兵收入基本上等于于手动内政,同条件下平均数自动内政是手动的92%
			// 但是毕竟3个武将行动+行动力是相当有意义的资源,因此削减自动内政10%左右的征兵收入.
			if (auto_inner::is_auto_affairs(building, actor_list)) // 只有在人数为1，开启自动内政，且有执政官经验时享受加成
			{
				// exp_eff = main.get_exp_eff(actor_list[0].get_id());
				exp_eff = auto_inner::get_exp_eff(actor_list[0].get_id(), 内政自动化_招兵);
				absent_eff = auto_inner::get_absent_eff(actor_list[0], 内政自动化_招兵);

				auto building_p = ch::get_baseIA(building_id);
				expend_eff = pk::min(3.0f, building_p.troops_effic / 300.0) * 1.2; // 执政官经验倍率由于无法互动而降低了,在这里暂时补上这部分损失的值
			}

			// 照顾港关征兵，加了默认值
			float barracks_buf = 1.1f;
			int porder = 60;
			pk::city @city;
			if (pk::is_valid_city_id(building_id))
			{
				@city = pk::building_to_city(building); // 这样港关征兵应该会出问题才是
				barracks_buf = main.func_5c4600(city);
				porder = city.public_order;
			}
			else
			{
				auto base_t = ch::get_base_p(building_id);
				porder = base_t.public_order;
			}

			 //pk::trace(pk::format("城市id：{},城市名:{},sum:{},mul:{},expend_eff:{},barracks_buf:{},n:{}", building.get_id(),pk::decode(pk::get_name(building)),sum,mul,expend_eff,barracks_buf,n));

			// 装备生产的公式，作为参考 n = (sum + max + 200) * 5 * mul / 100 *falcility_buf * pro / 100;//;//pro是制造数量倍率
			n = int((250 + (pk::min(porder, 95) + 5) * pk::max(200, pk::min(500, sum + max + 100)) * exp_eff * 3.0f / 100) * mul / 100 * barracks_buf * absent_eff * expend_eff);
			// pk::trace(pk::format("城市id：{},城市名:{},sum:{},mul:{},porder:{},barracks_buf:{},n:{}", building.get_id(),pk::decode(pk::get_name(building)),sum,mul,porder,(porder + 20) * (sum + max) * exp_eff * 1.0f / 100,n));

			// 以下是改公式时的计算过程
			//(sum + max + 200) * 5------------------------------------------------------(1000+5*(sum+max))*buf()
			//(1000+(porder + 20) * sum * 5 / 100)---(1000+(100 + 20) * sum * 5 / 100)---(1000+6*sum)*buf(1~1.5*1~1.5)--1000+6*120=1720=3870---1000+6*360=3160=7110---1000+6*70=1420=3195----1000+6*210=2260=5085
			//----------------------------------------------------------------------------------------------------------1000+3*240=1720=3870---1000+3*480=2440=5490---1000+3*140=1420=3195---1000+3*280=1840=4140

			if (pk::enemies_around(building))
				n = n * 兵临城下时征兵倍率 / 100;

			// -----------------------------------------------------------------------------
			// 玩家电脑区别对待
			n = int(n * (building.is_player() ? 玩家征兵倍率 : 电脑征兵倍率) / 100.f);

		// 难度修正
			n = int(n * (building.is_player() ? 100 : inter::domestic_difficulty_impact()) / 100.f);

				// 兵役政策影响
				// auto building_p = ch::get_baseIA(building_id);
				// float 兵役政策影响 = pk::clamp(1 + (2 - int(building_p.building_policy)) * 0.1, 0.8, 1.2);
				// n = int(n * 兵役政策影响); // 兵役政策对征兵效率略有影响
				// pk::trace(pk::format("{},兵役政策影响:{},兵役人数影响:{},兵役政策:{}", pk::decode(pk::get_name(base)), 兵役政策影响, 兵役人数影响,building_p.building_policy));

			if (征兵数_城市数_修正 and building.is_player() and !pk::is_campaign())
			{
				pk::force @force = pk::get_force(building.get_force_id());
				float force_city_count = float(pk::get_city_list(force).count);
				n = int(n * (1.f - (force_city_count * 0.02f)));
			}

			auto base_t = ch::get_base_p(building_id);
			int mil_all = base_t.mil_pop_all;
			if (mil_all < n)
			{
				if (base_t.population <= 5000)
				{
					return 0; // 参考san14，5000人口无法征兵
				}
				if (mil_all <= 0)
				{
					n = 200;
					if (type == 0)
					{
						ch::add_population(building_id, -2000); // 兵役人口不足时，从总人口强征，副作用较大
					}
				}
				else if (mil_all <= 200)
				{
					n = 200;
					if (type == 0)
					{
						ch::add_mil_pop_all(building_id, -mil_all);							 // base_t.mil_pop_av -= mil_all;
						ch::add_population(building_id, -uint32((200.f - mil_all) * 10.f)); // base_t.population -= uint32((200.f - mil_all)*10.f);//兵役人口不足时，从总人口强征，副作用较大
					}
				}
				else
				{
					n = mil_all;
					if (type == 0)
					{
						ch::add_mil_pop_all(building_id, -mil_all);
					}
				}
				// if (!building.is_player() and n <= 1500)
				// 	return 1500; // 电脑的征兵保底
			}
			else if (mil_all >= n)
			{
				if (type == 0)
				{
					ch::add_mil_pop_all(building_id, -n);
				}
				return n;

			}
			// -----------------------------------------------------------------------------
		}
		return n;
	}
}